﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Linq.Expressions;
using System.IO;

namespace CoolCode.Data.Linq
{
    public partial  class XDataContext : DataContext
    {
        private const bool withLog = false  ;
        private static TextWriter  sw;

        public XDataContext(string connectionString)
            : base(connectionString)
        {
            initialLog();
        }

        public XDataContext(string connectionString, MappingSource mappingSource)
            : base(connectionString, mappingSource)
        {
            initialLog();
        }

        public IExecuteResult ExecuteStoredProcedure(object instance, MethodInfo method, params object[] parameters)
        {
            return this.ExecuteMethodCall(instance , method, parameters);
        }

        public  IQueryable<T> ExecuteFunction<T>(object instance, MethodInfo method, params object[] parameters)
        { 
            return this.CreateMethodCallQuery<T>(instance , method, parameters);
        }

        private void initialLog()
        {
            if (withLog)
            {
                if (sw == null)
                {
                    string path=Path.Combine(Directory.GetCurrentDirectory(), "log.txt");
                    var  fs = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                    sw = new StreamWriter(fs);
                }
                this.Log = sw;
            }
        }

        public override void SubmitChanges(ConflictMode failureMode)
        {
            base.SubmitChanges(failureMode);
            if (sw != null)
            {
                sw.Flush();
            }
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
            if (sw != null)
            {
                sw.Flush();
                sw.Dispose();
            }
        } 
    }

    public  class DataContextFactory
    {
        public static string GetConnectionString()
        {
            return  System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
        }

        public static XDataContext Create()
        {
           return Create( GetConnectionString());
        }

        public static XDataContext Create(string connectionString)
        {
            var context = new XDataContext(connectionString);
            return context;
        }

        public static XDataContext Create(string connectionString, MappingSource mappingSource)
        {
            var context = new XDataContext(connectionString, mappingSource);
            return context;
        }
    }

    public static class RepositoryFactory
    {
        public static IRepository<T> Create<T>(this XDataContext context) where T : class
        {
            var rep = new Repository<T>(context);
            return rep;
        }
    }
}
